from collections import Iterable

from sqlalchemy import Column, Integer, String
from flask_sqlalchemy import SQLAlchemy
from web.control.error.error_code import SQLException, SQLMissException, Success, DeleteException
db = SQLAlchemy()


class BaseModel(db.Model):
    __abstract__ = True

    def set_attrs(self, form_dict):
        """
        对模型进行自动赋值
        :param form_dict: 要插入的数据
        :type form_dict: dict
        :return: 无返回值
        """
        for key, value in form_dict.items():
            if hasattr(self, key) and key != 'id':
                setattr(self, key, value)

    def add(self):
        """
        开启会话提交数据到数据库

        :return:无返回值
        """
        try:
            db.session.add(self)
            db.session.flush()
            id = self.id
            db.session.commit()
        except Exception as error:
            raise SQLException(msg=error)
        return Success(msg="数据添加成功", data=id)

    def delete(self):
        """
        删除数据库的数据

        :return: 无返回值
        """
        try:
            db.session.delete(self)
            db.session.commit()
        except Exception as error:
            raise DeleteException()
        return Success(msg="数据删除成功")

    def put(self, dataDict):
        """
        修改数据库的数据

        :param dataDict: 需要修改的数据
        :type dataDict: dict
        :return: 无返回值
        """
        try:
            self.set_attrs(dataDict)
            db.session.commit()
        except Exception as error:
            raise SQLException(msg=error)
        return Success(msg="数据修改成功")

    @staticmethod
    def query_all(cls):
        """
        查询表中所有的数据

        :param cls: 待查询表的映射模型
        :type cls: class
        :return: 一个可迭代的映射模型集合
        """
        try:
            data = cls.query.all()
        except Exception as error:
            raise SQLMissException(msg=error)
        result = cls.query_data(data)
        return result

    @staticmethod
    def query_data(queryResult):
        """
        将查询到的数据转换成list列表方便接口返回
        分两种情况，一种查询结果可迭代（即多条数据）
        一种查询结果不可迭代（只有一条数据）

        :param queryResult: 一个可迭代的映射模型集合,或一个类
        :type queryResult: class或set都可
        :return: 查询结果列表
        """
        datalist = []
        if isinstance(queryResult, Iterable):
            for i in queryResult:
                datadict = i.__dict__
                datadict.pop('_sa_instance_state')
                datalist.append(datadict)
        else:
            datadict = queryResult.__dict__
            datadict.pop('_sa_instance_state')
            datalist.append(datadict)
        return datalist





